﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using M3G;

namespace MyTestProject {

    public class TestMesh {

        [Fact]
        public void TestConstructor () {
            var msh = new Mesh (1, 1);

            Assert.Equal (1, msh.SubmeshCount);
            Assert.Equal (null, msh.VertexBuffer);
            Assert.Equal (null, msh.IndexBuffer[0]);
            Assert.Equal (null, msh.Appearance[0]);
            Assert.Equal (null, msh.ShaderAppearance[0]);
            Assert.Equal (1, msh.MorphTargetCount);
            Assert.Equal (null, msh.MorphTarget[0]);
            Assert.Equal (0, msh.Weights[0]);
        }

        [Fact]
        public void TestSetVertexBuffer () {
            var msh = new Mesh (1, 1);
            var vbuf = new VertexBuffer ();

            msh.SetVertexBuffer (vbuf);

            Assert.Equal (vbuf, msh.VertexBuffer);
        }

        [Fact]
        public void TestSetIndexBuffer () {
            var msh = new Mesh (2, 1);
            var ibuf1 = new IndexBuffer (PrimitiveType.PointSprites, 1, 0);
            var ibuf2 = new IndexBuffer (PrimitiveType.PointSprites, 1, 0);

            msh.SetIndexBuffer (0, ibuf1);
            msh.SetIndexBuffer (1, ibuf2);

            Assert.Equal (ibuf1, msh.IndexBuffer[0]);
            Assert.Equal (ibuf2, msh.IndexBuffer[1]);
        }

        [Fact]
        public void TestSetAppearance () {
            var msh = new Mesh (2, 1);
            var app1 = new Appearance ();
            var app2 = new Appearance ();

            msh.SetAppearance (0, app1);
            msh.SetAppearance (1, app2);

            Assert.Equal (app1, msh.Appearance[0]);
            Assert.Equal (app2, msh.Appearance[1]);
        }

        [Fact]
        public void TestGetShaderAppearance () {
            var msh = new Mesh (2, 1);
            var app1 = new ShaderAppearance ();
            var app2 = new ShaderAppearance ();

            msh.SetShaderAppearance (0, app1);
            msh.SetShaderAppearance (1, app2);

            Assert.Equal (app1, msh.ShaderAppearance[0]);
            Assert.Equal (app2, msh.ShaderAppearance[1]);
        }

        [Fact]
        public void TestSetMorphTarget () {
            var msh = new Mesh (1, 2);
            var vbuf1 = new VertexBuffer ();
            var vbuf2 = new VertexBuffer ();

            msh.SetMorphTarget (0, vbuf1);
            msh.SetMorphTarget (1, vbuf2);

            Assert.Equal (2, msh.MorphTargetCount);
            Assert.Equal (vbuf1, msh.MorphTarget[0]);
            Assert.Equal (vbuf2, msh.MorphTarget[1]);
        }

        [Fact]
        public void TestSetWeights () {
            var msh     = new Mesh (1, 2);
            var weights = new float[] {1f, 2f};

            msh.SetWeights (weights);

            Assert.Equal (2, msh.MorphTargetCount);
            Assert.Equal (1.0f, msh.Weights[0]);
            Assert.Equal (2.0f, msh.Weights[1]);
        }
        
        [Fact]
        public void TestSetMorphSubset () {
            var msh = new Mesh (1, 1);
            int[] indices = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 };

            msh.SetMorphSubset (4, indices);

            var expected = new int[] { 0, 1, 2, 3, 0, 0, 0, 0 };
            var outIndices = new int[8];

            Assert.Equal (4, msh.GetMorphSubset (outIndices));
            Assert.Equal (expected, outIndices);
        }

        [Fact]
        public void TestDuplicate () {
            var vbuf = new VertexBuffer ();
            var ibuf = new IndexBuffer (PrimitiveType.PointSprites, 1, 0);
            var app1 = new Appearance ();
            var app2 = new ShaderAppearance ();
            var morphTarget = new VertexBuffer ();
            var morphWeights = new float[] { 1f };
            var morphSubsetIndices = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 };
            var msh = new Mesh (1, 1);

            msh.SetVertexBuffer (vbuf);
            msh.SetIndexBuffer (0, ibuf);
            msh.SetAppearance (0, app1);
            msh.SetShaderAppearance (0, app2);
            msh.SetWeights (morphWeights);
            msh.SetMorphTarget (0, morphTarget);
            msh.SetMorphSubset (8, morphSubsetIndices);
            msh.UserID = 100;

            var grp = new Group ();
            grp.AddChild (msh);

            var dup = (Mesh)msh.Duplicate ();

            Assert.Equal (null, dup.Parent);
            Assert.Equal (msh.SubmeshCount, dup.SubmeshCount);
            Assert.Equal (msh.VertexBuffer, dup.VertexBuffer);
            Assert.Equal (msh.IndexBuffer[0], dup.IndexBuffer[0]);
            Assert.Equal (msh.Appearance[0], dup.Appearance[0]);
            Assert.Equal (msh.ShaderAppearance[0], dup.ShaderAppearance[0]);
            Assert.Equal (msh.MorphTargetCount, dup.MorphTargetCount);
            Assert.Equal (msh.MorphTarget[0], dup.MorphTarget[0]);
            Assert.Equal (msh.Weights[0], dup.Weights[0]);
            Assert.Equal (msh.UserID, dup.UserID);
        }
    }
}
